<?php

namespace app\api\controller;

use app\common\controller\Api;

/**
 * 支付请求
 */
class Pay extends Api
{
    protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['*'];
    protected $zh_cn = ['wxpay'=>'微信支付','qqpay'=>'QQ钱包','alipay'=>'支付宝'];
    protected $h5 = false;
    protected $charge = false;

    public function _initialize(){
        header("Content-Type: text/html;charset=utf-8");
    }

    public function submit(){
        // 提交方式
        $input = input('post.pid') ? 'post.' : 'get.';
        $input = input('post.api_id') ? 'post.' : $input;
         // 必须参数
        $validate = ['api_id', 'out_trade_no', 'return_url', 'notify_url', 'title', 'money', 'sign'];
        // 所有参数
        $data = [
            'api_id'=>input($input.'api_id')?input($input.'api_id'):input($input.'pid'),
            'out_trade_no'=>input($input.'out_trade_no'),
            'notify_url'=>input($input.'notify_url'),
            'return_url'=>input($input.'return_url'),
            'title'=>input($input.'title')?input($input.'title'):input($input.'name'),
            'money'=>input($input.'money'),
            'sign'=>input($input.'sign'),
            'sign_type'=>input($input.'sign_type'),
        ];
        $data['type'] = input($input.'type');
        // 验证参数
        foreach ($validate as $k => $v) {
            if (!$data[$v]) $this->html('缺少参数：'.$v);
            $action = '_'.$v;
            if(method_exists($this,$action)){
                $vd = $this->$action($data[$v]);
                if (isset($vd['code']) && !$vd['code']) $this->html(isset($vd['msg'])?$vd['msg']:'参数验证出错：'.$v);
            }
        }
        // 验证签名
        $queryArr = input($input);
        if(cache($data['out_trade_no'].'name') && isset($queryArr['name'])) $queryArr['name'] = cache($data['out_trade_no'].'name'); 
        if(cache($data['out_trade_no'].'sitename') && isset($queryArr['sitename'])) $queryArr['sitename'] = cache($data['out_trade_no'].'sitename');

        $prestr = createLinkstring(argSort(paraFilter($queryArr)));
        $res = $this->CommonUserModel->where(['api_id'=>$data['api_id']])->find();
        $user_key = isset($res['api_key']) ? $res['api_key'] : md5(time().rand(10000,99999));
        if(!md5Verify($prestr, $queryArr['sign'], $user_key)) $this->html('签名校验失败!');
        if ($res['status'] == 'hidden') $this->html('商户状态不正常');
        // 变量
        $money = round($data['money'],2);
        if (is_numeric(config('site.min_price')) && $money < config('site.min_price')) {
            $this->html('最低支付金额'.config('site.min_price').'元!');
        }
        
		$name = 'onlinepay-'.time();
        $http = substr($this->request->domain(),0,7) == 'http://' ? 'http://' : 'https://';
        // 可用支付渠道
        $row_type = ['wxpay','qqpay','alipay'];
        $type_ok = [];
        foreach ($row_type as $k => $v) {
            $type_ok[$v] = true;
        }
        foreach ($row_type as $k => $v) {
            if (config('site.'.$v).'' !== '1') $type_ok[$v] = false;
            if ($res[$v] !== 1) $type_ok[$v] = false;
        }

        if($data['type'] !== 'wxpay' && $data['type'] !== 'qqpay' && $data['type'] !== 'alipay'){
            $c = ['wxpay'=>'微信支付','qqpay'=>'QQ钱包','alipay'=>'支付宝'];
            $form = '';
            $type = '';
            foreach ($type_ok as $k => $v) {
                if ($k && $v) {
                    $param = input($input);
                    $param['type'] = $k;
                    $params = ['pid' => 0, "type" => 0,"out_trade_no"=>0, "notify_url" => 0, "return_url" => 0, "out_trade_no" => 0, 'name' => 0, "money" => 0];
                    foreach ($params as $a => $b) {
                        if (!isset($param[$a])) {
                            $s = false;
                            break;
                        }else{
                            $params[$a] = $param[$a];
                        }
                    }
                    $obj = new \pay\Easy();
                    $data = $obj->submit2([
                        'id'=>$params['pid'],
                        'key'=>$user_key,
                        'money'=>$params['money'],
                        'name'=>$params['name'],
                        'apiurl'=>request()->domain().'/',
                        'notify_url'=>$params['notify_url'],
                        'return_url'=>$params['return_url'],
                        'type'=>$params['type'],
                        'trade_no'=>$params['out_trade_no'],
                    ]);
                    $form.=$data;
                    $type.='<a href="javascript:document.getElementById(\''.$k.'_submit\').click();" >'.$c[$k].'</a>&nbsp;';
                }
            }
            if ($form&&$type) {
                $this->html($type.$form);
            }else{
                $this->html('当前支付方式已关闭');
            }
        }

        // 验证当前渠道
        if (!$type_ok[$data['type']]) {
            $this->html('当前支付方式已关闭');
        }
        // 关键字
        $danger = explode('|', config('site.danger_list'));
        $danger = array_filter($danger);
        if ($danger) {
            foreach ($danger as $k => $v) {
                if (strpos($data['title'],$v) !== false) {
                    $this->html('该商品禁止出售！');
                }
            }
        }
        //
        
        $config = config('site.'.$data['type'].'_config');
        if($res['dd'] == 1) {
            $_config = json_decode($res[$data['type'].'_config'],true);
            if(isset($_config[0]) && $_config[0]['url_id'] && $_config[0]['key']) $config = $_config;
        }
        $num = is_numeric(config('site.'.$data['type'].'_log')) ? (config('site.'.$data['type'].'_log')+1) : -1;
        $log = isset($config[$num]) ? $num : 0;
        $config = isset($config[$num]) ? $config[$num] : $config[0];
        configEdit([$data['type'].'_log'=>$log]);
        $config['url_id'] = trim($config['url_id']);
        $config['id_email'] = trim($config['id_email']);
        $config['key'] = trim($config['key']);
        $config['appsecret'] = isset($config['appsecret'])?$config['appsecret']:'';

        $verify_url_notify = $http.config('site.api_url').'/api/Pay/verify_notify';
        $verify_url_return = $http.config('site.api_url').'/api/Pay/verify_return';
        $verify_url_qqpay = $http.config('site.api_url').'/api/Pay/qqpay_notify';
        $verify_url_wxpay = $http.config('site.api_url').'/api/Pay/wxpay_notify';
        // 保存订单
        $trade_no = date("YmdHis").rand(11111,99999);
        $validate_outTradeNo = $this->CommonPayOrderModel->where(['out_trade_no'=>$data['out_trade_no'],'status'=>1])->find();
        if ($validate_outTradeNo) $this->html('订单重复');
        $validate_outTradeNo = $this->CommonPayOrderModel->where(['out_trade_no'=>$data['out_trade_no']])->find();
        if ($validate_outTradeNo && $validate_outTradeNo['uid'] == $res['id'] && $validate_outTradeNo['type'] == $data['type']) {
            $trade_no = $validate_outTradeNo['trade_no'];
            $name = $validate_outTradeNo['buyer'];
            $orderId = $validate_outTradeNo['id'];
            db('pay_order')->where(['id'=>$orderId])->update(['money'=>$money,'type_b'=>$config['type'],'type'=>$data['type']]);
        }else{
            cache($data['out_trade_no'].'name',input('name'));
            cache($data['out_trade_no'].'sitename',input('sitename'));
            $this->CommonPayOrderModel->save([
                'trade_no'=>$trade_no,
                'out_trade_no'=>$data['out_trade_no'],
                'notify_url'=>$data['notify_url'],
                'return_url'=>$data['return_url'],
                'type'=>$data['type'],
                'type_b'=>'auth',
                'uid'=>$res['id'],
                'title'=>$data['title'],
                'money'=>$money,
                'realmoney'=>($this->charge?$c_money:0),
                'charge'=>($this->charge?1:0),
                'charge_money'=>($this->charge?$data['money']:0),
                'domain'=>parse_url($data['return_url'])['host'],
                'ip'=>$this->request->ip(),
                'status'=>0,
                'buyer'=>$name,
                'rate'=>($this->charge?$rate:100),
                'createtime'=>time(),
                'updatetime'=>0,
            ]);
            $orderId = $this->CommonPayOrderModel->id;
        }
        // 发起支付
        if ($config['type'] !== 'auth') {
            if ($config['type'] == 'easy') {
                $arr = [
                    'id' => $config['id_email'], 
                    'key' => $config['key'], 
                    'apiurl' => $config['url_id'], 
                    'money' => $money, 
                    'name' => $name, 
                    'type' => $data['type'], 
                    'notify_url' => $verify_url_notify, 
                    'return_url' => $verify_url_return, 
                    'trade_no' => $trade_no
                ];
                $this->CommonPayOrderModel->where(['id'=>$orderId])->update([
                    'config'=>serialize([
                        'id' => $config['id_email'], 
                        'key' => $config['key'], 
                        'apiurl' => $config['url_id']
                    ]),
                    'type_b'=>'easy',
                ]);
                $easy_html = EasyPay($arr);
                echo $easy_html;
                exit();
            }
            if ($config['type'] == 'ysh') {
                $this->CommonPayOrderModel->where(['id'=>$orderId])->update([
                    'config'=>serialize($config),
                    'type_b'=>'ysh',
                ]);
                $_getSign=function ($data, $appSecret)
                {
                    ksort($data);
                    $rows = [];
                    foreach ($data as $key => $value) {
                        if (! $value || $key == 'sign') {
                            continue;
                        }
                        $rows[] = "{$key}={$value}";
                    }
                    $s = implode('&', $rows);
                    $s .= $appSecret;

                    return strtoupper(md5($s));
                };
                $data = [
                    'app_key' => $config['key'],
                    'out_trade_no' => $trade_no,
                    'total_fee' => $money*100,
                    'subject' => $name,
                    'notify_url' =>  $http.config('site.api_url').'/api/Pay/ljzf_notify',
                    'sub_mch_id' => $config['id_email'],
                ];
                $data['sign'] = $_getSign($data, $config['appsecret']);
                if($this->request->isMobile()) $data['openid']='';
                $_request=function ($url, array $data)
                {
                     $ch = curl_init();
                    //设置选项，包括URL
                    curl_setopt($ch, CURLOPT_URL, $url);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                    curl_setopt($ch, CURLOPT_HEADER, 0);
                    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts
                    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
                    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
                    $output = curl_exec($ch);
                    curl_close($ch);
                    return $output;
                };
                $native_url = 'https://1shanghu.com/api/v2/wechat/native';
                $mp_url = 'https://1shanghu.com/api/v2/wechat/mp';
                if($this->request->isMobile()){
                    if(!input('get.openid')){
                        $row_url = $http.config('site.api_url').urldecode($_SERVER['REQUEST_URI']);
                      
                        $url = sprintf('https://1shanghu.com/v2/wechat/login?app_key=%s&sub_mch_id=%s&callback=%s', $config['key'],  $config['id_email'], urlencode($row_url));
                        if(strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger')!==false){
                            return redirect($url);
                        }
                        $urls = 'http://api.t.sina.com.cn/short_url/shorten.json?source=3271760578&url_long='.urlencode($url);
                        $json = getCurl(['url'=>$urls,'type'=>'get']);
                        $json = json_decode($json,true);
                        if (isset($json[0]['url_short'])) {
                            $url = $json[0]['url_short'];
                        }
                        return view('wxapppay', [
                          'money'  => $money,
                          'title'  => $name,
                          'url'  => $url,
                          'trade_no'  => $trade_no,
                          'code_url'  => $url,
                        ]);
                    }else{
                        if(cache('ddd'.$trade_no)){
                         return view('wxjspay', [
                              'jsApiParameters'  =>json_encode(cache('ddd'.$trade_no)),
                              'trade_no'  => $trade_no,
                        ]);
                        }
                        $openid = input('get.openid');
                        $data['openid'] = $openid;
                        $data['sign'] = $_getSign($data, $config['appsecret']);
                        $_data = $_request($mp_url, $data);
                        $json=json_decode($_data,true);
                        if(!isset($json['data']['jsapi_package']) || !$json['data']['jsapi_package']) $this->html('下单失败！');
                        $arr = [];
                        foreach($json['data'] as $k => $v){
                            if(strpos($k,'jsapi_') !==false){
                                $arr[substr($k,6)] = $v;
                            }
                        }
                        $arr['appId'] = $arr['app_id'];
                        cache('ddd'.$trade_no,$arr,3600);
                        return view('wxjspay', [
                              'jsApiParameters'  =>json_encode($arr),
                              'trade_no'  => $trade_no,
                        ]);
                    }
                }else{
                    if(!cache($trade_no.'native_lj')) {
                      $_data = $_request($native_url, $data);
                      $json=json_decode($_data,true);
                      if(!isset($json['data']['code_url']) || !$json['data']['code_url']) $this->html('下单失败！');
                      cache($trade_no.'native_lj',$json['data']['code_url'],86400);
                      $_url = $json['data']['code_url'];
                    }else{
                        $_url = cache($trade_no.'native_lj');
                    }
                    return view('wxpay', [
                        'money'  => $money,
                        'title'  => $name,
                        'trade_no'  => $trade_no,
                        'code_url'  => $_url,
                    ]);
                }
            }
        }
        switch ($data['type']) {
            case 'alipay':
                $service = $this->request->isMobile() ? "alipay.wap.create.direct.pay.by.user" : "create_direct_pay_by_user";
                $parameter = array(
                    "service" => $service,
                    "partner" => $config['url_id'],
                    "seller_id" => $config['url_id'],
                    "payment_type"  => "1",
                    "notify_url"    => $verify_url_notify,
                    "return_url"    => $verify_url_return,
                    "out_trade_no"  => $trade_no,
                    "subject"   => $name,
                    "total_fee" => $money,
                    "_input_charset"    => strtolower('utf-8')
                );
                if ($this->request->isMobile()) $parameter['app_pay'] = "Y";
                $alipay_config['partner'] = $config['url_id'];
                $alipay_config['seller_email'] = $config['id_email'];
                $alipay_config['key'] = $config['key'];
                $alipay_config['sign_type'] = strtoupper('MD5');
                $alipay_config['input_charset'] = strtolower('utf-8');
                $alipay_config['cacert'] = '\\cacert.pem';
                $alipay_config['transport'] = $http;
                $this->CommonPayOrderModel->where(['id'=>$orderId])->update(['config'=>serialize($alipay_config)]);
                $submit = new \pay\Alipay($alipay_config);
                $html_text = $submit->buildRequestForm($parameter,"get","正在跳转");
                echo $html_text;
                exit();
                break;

            case 'qqpay':
                $params = [];
                $params["out_trade_no"] = $trade_no;
                $params["body"] = $name;
                $params["fee_type"] = "CNY";
                $params["notify_url"] = $verify_url_qqpay;
                $params["spbill_create_ip"] = $this->request->ip();
                $params["total_fee"] = $money*100;
                $params["trade_type"] = "NATIVE";
                $obj = new \pay\Qpay('https://qpay.qq.com/cgi-bin/pay/qpay_unified_order.cgi', null, 10);
                $ret = $obj->reqQpay($params,$config['url_id'],$config['key']);
                $result = $obj->xmlToArray($ret);
                if($result['return_code']=='SUCCESS' && $result['result_code']=='SUCCESS'){
                    $code_url = $result['code_url'];
                }else{
                    $this->html('QQ钱包支付下单失败！请重试');
                }
                $this->CommonPayOrderModel->where(['id'=>$orderId])->update(['config'=>serialize(['id'=>$config['url_id'],'key'=>$config['key']])]);
                if(strpos($_SERVER['HTTP_USER_AGENT'], 'QQ/')!==false){
                    return redirect($code_url);
                }
                return view('qqpay', [
                    'money'  => $money,
                    'title'  => $params["body"],
                    'trade_no'  => $trade_no,
                    'code_url'  => $code_url,
                ]);
                break;
            
            case 'wxpay':
                config('wxpay_appid',$config['url_id']);
                config('wxpay_mchid',$config['id_email']);
                config('wxpay_key',$config['key']);
                config('wxpay_appsecret',$config['appsecret']);
                $wxpay_config = [
                    'wxpay_appid'=>config("wxpay_appid"),
                    'wxpay_mchid'=>config("wxpay_mchid"),
                    'wxpay_key'=>config("wxpay_key"),
                    'wxpay_appsecret'=>config("wxpay_appsecret"),
                ];
                $this->CommonPayOrderModel->where(['id'=>$orderId])->update(['config'=>serialize($wxpay_config)]);
                if(strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger')!==false){
                    $jspay = $this->jspay($trade_no,$money,$verify_url_wxpay,$name);
                    if (!$jspay['code']) {
                        $this->html($jspay['msg']);
                    }
                    return view('wxjspay', [
                        'jsApiParameters'  => $jspay['data'],
                        'trade_no'  => $trade_no,
                        'money'  => $money,
                    ]);
                }else{
                    $h5 = $config['h5'].'' == '1' ? true : false;
                    $iswx = $this->request->isMobile() ? true : false;
                    if ($iswx && !$h5) {
                        $href_url = $this->request->domain().'/api/Pay/wxapppay?trade_no='.$trade_no;
                        $url = 'http://api.t.sina.com.cn/short_url/shorten.json?source=3271760578&url_long='.$href_url;
                        $json = getCurl(['url'=>$url,'type'=>'get']);
                        $json = json_decode($json,true);
                        if (isset($json[0]['url_short'])) {
                            $href_url = $json[0]['url_short'];
                        }
                        return view('wxapppay', [
                            'url'  => $href_url,
                            'money'  => $money,
                            'title'  => $name,
                            'trade_no'  => $trade_no,
                        ]);
                    }
                    $notify = new \pay\wx\NativePay();
                    $input = new \pay\wx\WxPayUnifiedOrder();
                    $input->SetBody($name);
                    $input->SetOut_trade_no($trade_no);
                    $input->SetTotal_fee($money*100);
                    $input->SetSpbill_create_ip($this->request->ip());
                    $input->SetTime_start(date("YmdHis"));
                    $input->SetTime_expire(date("YmdHis", time() + 600));
                    $input->SetNotify_url($verify_url_wxpay);
                    if ($h5 && $iswx) {
                        $input->SetTrade_type("MWEB");
                    }else{
                        $input->SetTrade_type("NATIVE");
                    }
                    $result = $notify->GetPayUrl($input);
                    if ($h5 && $iswx) {
                        if($result["result_code"]=='SUCCESS'){
                            $redirect_url=$http.config('site.api_url').'/api/Pay/wxh5?trade_no='.$trade_no;
                            $url=$result['mweb_url'].'&redirect_url='.urlencode($redirect_url);
                            exit("<script>window.location.replace('{$url}');</script>");
                        }else{
                            $this->html('微信支付下单失败！');
                        }
                    }else{
                        if(isset($result['code_url']) && $result['code_url']){
                            $code_url=$result['code_url'];
                        }else{
                            $this->html('微信支付下单失败！');
                        }
                    }
                    return view('wxpay', [
                        'money'  => $money,
                        'title'  => $name,
                        'trade_no'  => $trade_no,
                        'code_url'  => $code_url,
                    ]);
                }
                break;
            
            default:
                $this->html('支付类型出错');
                break;
        }
    }

    public function ljzf_notify(){
        $out_trade_no = input('out_trade_no');
        $res = $this->CommonPayOrderModel->where(['trade_no'=>$out_trade_no])->find();

        if (!$res) $this->html('订单不存在！');
        if ($res['status'] == 1) {
            exit('success');
        }
        $config = unserialize($res['config']);
        $_getSign=function ($data, $appSecret)
        {
          ksort($data);
          $rows = [];
          foreach ($data as $key => $value) {
            if (! $value || $key == 'sign') {
              continue;
            }
            $rows[] = "{$key}={$value}";
          }
          $s = implode('&', $rows);
          $s .= $appSecret;

          return strtoupper(md5($s));
        };
      
        $end = strtoupper(input('sign')) == $_getSign(input(), $config['appsecret']);
        if(!$end){
            exit('no');
        }else{
            $data = orderEnd($res['id'],input('get.'),input('post.'),false);
          if (!$data['code']) $this->html($data['msg']);
          echo "success";
        }
    }

    public function wxh5(){
        $trade_no = input('get.trade_no');
        $res = $this->CommonPayOrderModel->where(['trade_no'=>$trade_no])->find();
        if (!$res) $this->html('订单不存在！');
        if ($res['type'] !== 'wxpay') $this->html('一边去');
        if ($res['status'] !== 0) {
            $user = $this->CommonUserModel->where(['id'=>$res['uid']])->find();
            if (!$user) return redirect($res['return_url']);
            $array=[
                'pid'=>$user['api_id'],
                'trade_no'=>$res['trade_no'],
                'out_trade_no'=>$res['out_trade_no'],
                'type'=>$res['type'],
                'name'=>$res['title'],
                'money'=>round($res['money'],2),
                'trade_status'=>'TRADE_SUCCESS'
            ];
            $arg = argSort(paraFilter($array));
            $prestr = createLinkstring($arg);
            $urlstr = createLinkstringUrlencode($arg);
            $sign = md5Sign($prestr, $user['api_key']);
            $n = strpos($res['return_url'],'?') ? '&' : '?';
            $url = $res['return_url'].$n.$urlstr.'&sign='.$sign.'&sign_type=MD5';
            return redirect($url);
            exit();
        }
        if (!$res['config']) $this->html('一边去');
        $config = unserialize($res['config']);
        if (!isset($config['wxpay_appid']) || !$config['wxpay_appid']) $this->html('一边去');
        if (!isset($config['wxpay_mchid']) || !$config['wxpay_mchid']) $this->html('一边去');
        if (!isset($config['wxpay_key']) || !$config['wxpay_key']) $this->html('一边去');
        if (!isset($config['wxpay_appsecret']) || !$config['wxpay_appsecret']) $this->html('一边去');
        config('wxpay_appid',$config['wxpay_appid']);
        config('wxpay_mchid',$config['wxpay_mchid']);
        config('wxpay_key',$config['wxpay_key']);
        config('wxpay_appsecret',$config['wxpay_appsecret']);
        return view('wxh5', [
            'trade_no'  => $trade_no,
        ]);
    }

    public function wxapppay(){
        $trade_no = input('get.trade_no');
        $res = $this->CommonPayOrderModel->where(['trade_no'=>$trade_no])->find();
        if ($res['type'] !== 'wxpay') $this->html('一边去');
        if ($res['status'] !== 0) $this->html('该订单已完成支付！');
        if (!$res['config']) $this->html('一边去');
        $config = unserialize($res['config']);
        if (!isset($config['wxpay_appid']) || !$config['wxpay_appid']) $this->html('一边去');
        if (!isset($config['wxpay_mchid']) || !$config['wxpay_mchid']) $this->html('一边去');
        if (!isset($config['wxpay_key']) || !$config['wxpay_key']) $this->html('一边去');
        if (!isset($config['wxpay_appsecret']) || !$config['wxpay_appsecret']) $this->html('一边去');
        config('wxpay_appid',$config['wxpay_appid']);
        config('wxpay_mchid',$config['wxpay_mchid']);
        config('wxpay_key',$config['wxpay_key']);
        config('wxpay_appsecret',$config['wxpay_appsecret']);
        $verify_url_wxpay = $this->request->domain().'/api/Pay/wxpay_notify';
        $jspay = $this->jspay($res['trade_no'],$res['money'],$verify_url_wxpay,$res['title']);
        if (!$jspay['code']) $this->html($jspay['msg']);
        return view('wxjspay', [
            'jsApiParameters'  => $jspay['data'],
            'trade_no'  => $trade_no,
        ]);
    }

    private function jspay($trade_no,$money,$notify,$name){
        if(session($trade_no.'_wxpay')){
            $jsApiParameters = session($trade_no.'_wxpay');
        }else{
            $tools = new \pay\wx\JsApiPay();
            $openId = $tools->GetOpenid();
            if(!$openId) return ['code'=>0,'msg'=>'OpenId获取失败！请退出重试'];
            $this->CommonPayOrderModel->where(['trade_no'=>$trade_no])->update(['buyer'=>$openId]);
            $input = new \pay\wx\WxPayUnifiedOrder();
            $input->SetBody($name);
            $input->SetOut_trade_no($trade_no);
            $input->SetTotal_fee($money*100);
            $input->SetTime_start(date("YmdHis"));
            $input->SetTime_expire(date("YmdHis", time() + 600));
            $input->SetNotify_url($notify);
            $input->SetTrade_type("JSAPI");
            $input->SetProduct_id("01001");
            $input->SetOpenid($openId);
            $order = \pay\wx\WxPayApi::unifiedOrder($input);
            if(isset($order["result_code"]) && $order["result_code"]=='SUCCESS'){
                $jsApiParameters = $tools->GetJsApiParameters($order);
            }else{
                return ['code'=>0,'msg'=>'微信支付下单失败！'];
            }
            session($trade_no.'_wxpay',$jsApiParameters);
        }
        return ['code'=>1,'msg'=>'OK','data'=>$jsApiParameters];
    }

    public function qqpay_notify(){
        $obj = new \pay\Qpay('', null, 10);
        $data = $obj->getParams();
        if (!isset($data['out_trade_no']) || !$data['out_trade_no']) $this->html('QQ钱包支付验证失败！');
        $res = $this->CommonPayOrderModel->where(['trade_no'=>$data['out_trade_no']])->find();
        if (!$res) $this->html('订单不存在！');
        if ($res['status'] == 1) {
            return redirect($res['return_url']);
            exit();
        }
        $config = unserialize($res['config']);
        if (!isset($config['key'])) $this->html('QQ钱包支付验证失败！');
        if($obj->verifySign($config['key'])) {
            if($data['trade_state'] !== "SUCCESS") $this->html('QQ钱包支付验证失败！');
            $data = orderEnd($res['id'],input('get.'),input('post.'),$data);
            if (!$data['code']) $this->html($data['msg']);
            $this->CommonPayOrderModel->where(['id'=>$res['id']])->update(['status'=>1]);
        }else{
            $this->html('QQ钱包支付验证失败！');
        }
    }

    public function wxpay_notify(){
        $notify = new \pay\wx\Notify();
        $notify->Handle(false);
    }

    // 支付回调
    public function verify_notify(){
        $out_trade_no = input('out_trade_no');
        $res = $this->CommonPayOrderModel->where(['trade_no'=>$out_trade_no])->find();
        if (!$res) $this->html('订单不存在！');
        if ($res['status'] == 1) {
            return redirect($res['return_url']);
            exit();
        }
        $config = unserialize($res['config']);
        if ($res['type_b'] == 'easy') { // 易支付
            $verify = EasyPay($config,false);
            if (!$verify) $this->html('支付验证出错！');
        }else{ // 官方
            if ($res['type'] == 'alipay') {
                $obj = new \pay\AlipayNotify($config);
                $verify = $obj->verifyNotify();
                if(!$verify) $this->html('支付验证出错！');
                if (input('post.trade_status') !== 'TRADE_SUCCESS') $this->html('支付验证出错！');
            }else{
                $this->html('订单出错咯');
            }
        }
        $data = orderEnd($res['id'],input('get.'),input('post.'),$verify);
        if (!$data['code']) $this->html($data['msg']);
        return redirect($data['url']);
    }

    public function verify_return(){
        $out_trade_no = input('out_trade_no');
        $res = $this->CommonPayOrderModel->where(['trade_no'=>$out_trade_no])->find();
        if (!$res) $this->html('订单不存在！');
        if ($res['status'] == 1) {
            $user = $this->CommonUserModel->where(['id'=>$res['uid']])->find();
            if (!$user) return redirect($res['return_url']);
            $array=[
                'pid'=>$user['api_id'],
                'trade_no'=>$res['trade_no'],
                'out_trade_no'=>$res['out_trade_no'],
                'type'=>$res['type'],
                'name'=>$res['title'],
                'money'=>($res['charge']?$res['realmoney']:$res['money']),
                'trade_status'=>'TRADE_SUCCESS'
            ];
            $arg = argSort(paraFilter($array));
            $prestr = createLinkstring($arg);
            $urlstr = createLinkstringUrlencode($arg);
            $sign = md5Sign($prestr, $user['api_key']);
            $n = strpos($res['return_url'],'?') ? '&' : '?';
            $url = $res['return_url'].$n.$urlstr.'&sign='.$sign.'&sign_type=MD5';
            return redirect($url);
            exit();
        }
        $config = unserialize($res['config']);
        if ($res['type_b'] == 'easy') { // 易支付
            $verify = EasyPay($config,false);
            if (!$verify) $this->html('支付验证出错！');
        }else{ // 官方
            if ($res['type'] == 'alipay') {
                $obj = new \pay\AlipayNotify($config);
                $verify = $obj->verifyReturn();
                if(!$verify) $this->html('支付验证出错！');
                if (input('get.trade_status') !== 'TRADE_FINISHED' && input('get.trade_status') !== 'TRADE_SUCCESS') $this->html('支付验证出错！');
            }else{
                $this->html('订单出错咯');
            }
        }
        $data = orderEnd($res['id'],input('get.'),input('post.'),$verify);
        if (!$data['code']) $this->html($data['msg']);
        return redirect($data['url']);
    }

    public function pay_verify(){
        $trade_no = input('trade_no');
        $res = $this->CommonPayOrderModel->where(['trade_no'=>$trade_no])->find();
        if ($res['status'] == 1) {
            $user = model('User')->where(['id'=>$res['uid']])->find();
            if ($user) {
                $array=[
                    'pid'=>$user['api_id'],
                    'trade_no'=>$res['trade_no'],
                    'out_trade_no'=>$res['out_trade_no'],
                    'type'=>$res['type'],
                    'name'=>$res['title'],
                   'money'=>($res['charge']?$res['realmoney']:$res['money']),
                    'trade_status'=>'TRADE_SUCCESS'
                ];
                $arg = argSort(paraFilter($array));
                $prestr = createLinkstring($arg);
                $urlstr = createLinkstringUrlencode($arg);
                $sign = md5Sign($prestr, $user['api_key']);
                $n = strpos($res['return_url'],'?') ? '&' : '?';
                $url = $res['return_url'].$n.$urlstr.'&sign='.$sign.'&sign_type=MD5';
            }else{
                $url = $res['return_url'];
            }
            return json(['code'=>1,'msg'=>'OK','url'=>$url]);
        }else{
            return json(['code'=>0,'msg'=>'Not Ok']);
        }
    }

    // 彩虹暂适应接口
    public function api(){
        $action = $this->request->get('act');
        switch ($action) {
            case 'order': //查询单个订单
                $pid = $this->request->param('pid');
                $key = $this->request->param('key');
                $out_trade_no = $this->request->param('out_trade_no');
                if (!$pid) exit(json_encode(['code'=>0,'msg'=>'请提交商户ID']));
                if (!$key) exit(json_encode(['code'=>0,'msg'=>'请提交商户Key']));
                if (!$out_trade_no) exit(json_encode(['code'=>0,'msg'=>'请提交订单号']));
                $res = model('PayOrder')->where(['out_trade_no'=>$out_trade_no])->find();
                if (!$res) exit(json_encode(['code'=>0,'msg'=>'订单不存在']));
                $user = model('User')->where(['id'=>$res['uid']])->find();
                if (!$user) exit(json_encode(['code'=>0,'msg'=>'订单不存在']));
                if ($user['api_id'].''!==$pid.'' || $user['api_key']!==$key) exit(json_encode(['code'=>0,'msg'=>'订单不存在']));
                exit(json_encode([
                    'code'=>1,
                    'msg'=>'OK',
                    'trade_no'=>$res['trade_no'],
                    'out_trade_no'=>$res['out_trade_no'],
                    'type'=>$res['type'],
                    'pid'=>$pid,
                    'addtime'=>date('Y-m-d H:i:s',$res['createtime']),
                    'endtime'=>!$res['updatetime'] ? 0 : date('Y-m-d H:i:s',$res['updatetime']),
                    'name'=>$res['title'],
                    'money'=>$res['money'],
                    'status'=>$res['status'],
                ]));
                break;

            case 'orders': //批量查询订单
                $pid = $this->request->param('pid');
                $key = $this->request->param('key');
                $limit = $this->request->param('limit');
                $limit = !preg_match("/^[1-9][0-9]*$/",$limit) ? 50 : $limit;
                $limit = $limit>50 ? 50 : $limit;
                if (!$pid) exit(json_encode(['code'=>0,'msg'=>'请提交商户ID']));
                if (!$key) exit(json_encode(['code'=>0,'msg'=>'请提交商户Key']));
                $user = model('User')->where(['api_id'=>$pid,'api_key'=>$key])->find();
                if (!$user) exit(json_encode(['code'=>0,'msg'=>'商户不存在']));
                $res = model('PayOrder')->where(['uid'=>$user['id']])->order('trade_no desc')->limit($limit)->select();
                if (!$res) exit(json_encode(['code'=>0,'msg'=>'没有订单']));
                $data = [];
                foreach ($res as $k => $v) {
                    $data[] = [
                        'trade_no'=>$v['trade_no'],
                        'out_trade_no'=>$v['out_trade_no'],
                        'status'=>$v['status'],
                        'addtime'=>date('Y-m-d H:i:s',$v['createtime']),
                        'endtime'=>!$v['updatetime'] ? 0 : date('Y-m-d H:i:s',$v['updatetime']),
                        'name'=>$v['title'],
                        'money'=>$v['money'],
                        'pid'=>$user['api_id'],
                        'type'=>$v['type'],
                    ];
                }
                exit(json_encode(['code'=>1,'msg'=>'OK','data'=>$data]));
                break;

            case 'query': //查询商户信息与结算规则
                $pid = $this->request->param('pid');
                $key = $this->request->param('key');
                if (!$pid) exit(json_encode(['code'=>0,'msg'=>'请提交商户ID']));
                if (!$key) exit(json_encode(['code'=>0,'msg'=>'请提交商户Key']));
                $user = model('User')->where(['api_id'=>$pid,'api_key'=>$key])->find();
                if (!$user) exit(json_encode(['code'=>0,'msg'=>'商户不存在']));
                exit(json_encode([
                    'code'=>1,
                    'msg'=>'OK',
                    'pid'=>$pid,
                    'key'=>$key,
                    'type'=>1,
                    'active'=>$user['status'] == 'normal' ? 1 : 0,
                    'money'=>$user['money'],
                    'account'=>$user['withdraw_account'],
                    'username'=>$user['withdraw_name'],
                    'settle_money'=>config('site.withdraw_need'),
                    'settle_fee'=>config('site.withdraw_money'),
                    'money_rate'=>config('site.default_rate'),
                ]));
                break;

            case 'settle': //查询结算记录
                $pid = $this->request->param('pid');
                $key = $this->request->param('key');
                if (!$pid) exit(json_encode(['code'=>0,'msg'=>'请提交商户ID']));
                if (!$key) exit(json_encode(['code'=>0,'msg'=>'请提交商户Key']));
                $user = model('User')->where(['api_id'=>$pid,'api_key'=>$key])->find();
                if (!$user) exit(json_encode(['code'=>0,'msg'=>'商户不存在']));
                $withdraw = model('Withdraw')->where(['uid'=>$user['id']])->select();
                if (!$withdraw) exit(json_encode(['code'=>0,'msg'=>'没有结算记录']));
                $data = [];
                foreach ($withdraw as $k => $v) {
                    $data[] = [
                        'id'=>$v['id'],
                        'pid'=>$pid,
                        'batch'=>$v['mark'] ? $v['mark'] : '0',
                        'type'=>$v['type'],
                        'username'=>$v['withdraw_name'],
                        'account'=>$v['withdraw_account'],
                        'money'=>$v['money'],
                        'fee'=>$v['percent'],
                        'time'=>date('Y-m-d H:i:s',$v['createtime']),
                        'status'=>$v['status'],
                    ];
                }
                exit(json_encode(['code'=>1,'msg'=>'OK','data'=>$data]));
                break;

            case 'change': //修改结算账号
                $this->html('已关闭接口修改结算账号');
                break;
            
            default:
                exit(json_encode(['code'=>0,'msg'=>'接口方法不存在']));
                break;
        }
    }

    private function _api_id($e){
        if(!preg_match("/^[1-9][0-9]*$/",$e)) return ['code'=>0,'msg'=>'Api_Id错误'];
    }
    private function _type($e){
        if($e !== 'wxpay' && $e !== 'qqpay' && $e !== 'alipay') return ['code'=>0,'msg'=>'支付方式出错'];
    }
    private function _out_trade_no($e){
        if(!preg_match('/^[a-zA-Z0-9.\_\-|]+$/',$e)) return ['code'=>0,'msg'=>'订单号格式出错'];
    }
    private function _money($e){
        $e = round($e,2);
        if(!is_numeric($e) || $e <= 0) return ['code'=>0,'msg'=>'支付金额只能为正浮点数'];
        if($e > 9999) return ['code'=>0,'msg'=>'支付金额过大，请分批付款'];
    }

    protected function json($code,$msg='',$data=''){
        $content = ['code'=>($code ? 1 : 0),'msg'=>$msg];
        if ($data) $content['data'] = $data;
        $json = json_encode($content);
        exit($json);
    }

    protected function html($data){
        $str = '
        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
        <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=0.5, maximum-scale=2.0, user-scalable=yes" />  
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <title>跳转提示</title>';
        if($this->request->isMobile()){
            $str.= '
            <style type="text/css">
                body, h1, h2, p,dl,dd,dt{margin: 0;padding: 0;font: 15px/1.5 微软雅黑,tahoma,arial;}
                body{background:#efefef;}
                h1, h2, h3, h4, h5, h6 {font-size: 100%;cursor:default;}
                ul, ol {list-style: none outside none;}
                a {text-decoration: none;color:#447BC4}
                a:hover {text-decoration: underline;}
                .ip-attack{width:100%; margin:200px auto 0;}
                .ip-attack dl{ background:#fff; padding:30px; border-radius:10px;border: 1px solid #CDCDCD;-webkit-box-shadow: 0 0 8px #CDCDCD;-moz-box-shadow: 0 0 8px #cdcdcd;box-shadow: 0 0 8px #CDCDCD;}
                .ip-attack dt{text-align:center;}
                .ip-attack dd{font-size:16px; color:#333; text-align:center;}
                .tips{text-align:center; font-size:14px; line-height:50px; color:#999;}
            </style>';
        }else{
            $str.= '
            <style type="text/css">
                body, h1, h2, p,dl,dd,dt{margin: 0;padding: 0;font: 15px/1.5 微软雅黑,tahoma,arial;}
                body{background:#efefef;}
                h1, h2, h3, h4, h5, h6 {font-size: 100%;cursor:default;}
                ul, ol {list-style: none outside none;}
                a {text-decoration: none;color:#447BC4}
                a:hover {text-decoration: underline;}
                .ip-attack{width:600px; margin:200px auto 0;}
                .ip-attack dl{ background:#fff; padding:30px; border-radius:10px;border: 1px solid #CDCDCD;-webkit-box-shadow: 0 0 8px #CDCDCD;-moz-box-shadow: 0 0 8px #cdcdcd;box-shadow: 0 0 8px #CDCDCD;}
                .ip-attack dt{text-align:center;}
                .ip-attack dd{font-size:16px; color:#333; text-align:center;}
                .tips{text-align:center; font-size:14px; line-height:50px; color:#999;}
            </style>
            ';
        }
        $str.= '
            </head>
            <body>

                <div class="ip-attack">
                <dl>
                    <dt>
                        <font style="color: red">'.$data.'</font>
                    </dt>';
        $str.= '</dl>
                </div>
            </body>
            </html>
        ';
        exit($str);
    }
}
